#include "pch.h"
#include "Info.h"


#define STRINGIFY(x) #x

std::vector<std::string> splitString(const std::string &s, char delimiter)
{
    std::vector<std::string> tokens;
    std::stringstream ss(s);
    std::string token;
    while (std::getline(ss, token, delimiter))
    {
        tokens.push_back(token);
    }
    return tokens;
}

const char *instHTemp = R"(#pragma once


namespace %s
{
    namespace %s
    {
        namespace %s
        {
            namespace %s
            {
                struct Inst
                {
                };
            }
        } 
    }
};)";

const char *editorHTemp = R"(#pragma once

#include <imgui/imgui.h>
#include <%s/%s/%s/%s/Inst.h>

namespace %s
{
    namespace %s
    {
        namespace %s
        {
            namespace %s
            {
                struct Editor
                {
                    bool Edit(Inst& inst);
                };
            }
        } 
    }
};)";

const char *serializerHTemp = R"(#pragma once

#include <yaml-cpp/yaml.h>
#include <%s/%s/%s/%s/Inst.h>

namespace %s
{
    namespace %s
    {
        namespace %s
        {
            namespace %s
            {
                struct Serializer
                {
                    bool Encode(YAML::Node &node, const Inst &inst);

                    bool Decode(const YAML::Node &node, Inst &inst);
                
                };
            }
        } 
    }
};)";
const char *instCppTemp = R"(

#include <imgui/imgui.h>
#include <%s/%s/%s/%s/Inst.h>

using namespace %s::%s::%s::%s;


)";
const char *editorCppTemp = R"(

#include <%s/%s/%s/%s/Editor.h>

using namespace %s::%s::%s::%s;

bool Editor::Edit(Inst &inst)
{

    ImGui::SetNextItemOpen(true);
    
    if (ImGui::CollapsingHeader("Simple Color"))
    {
    }

    return true;    
}


)";

const char *serializerCppTemp = R"(

#include <%s/%s/%s/%s/Serializer.h>

using namespace %s::%s::%s::%s;


bool Serializer::Encode(YAML::Node &node, const Inst &inst)
{

    return true;
};

bool Serializer::Decode(const YAML::Node &node, Inst &inst)
{

    return true;
};

)";

const char *cmakeListsTemp = R"(

cmake_minimum_required(VERSION 3.5.0)

set(CMAKE_CXX_STANDARD 17)


set(path_name %s_%s_%s_%s )

add_library(${path_name}_engine Editor.cpp Inst.cpp Serializer.cpp)
add_library(${path_name}_launcher Inst.cpp Serializer.cpp)

)";


std::string GetValue2(const char *temp, Info info)
{
    char res[512];

    std::vector<std::string> seps2 = info.tokens1;
    std::vector<std::string> seps = info.tokens2;

    sprintf(res, temp,
            seps2[0].c_str(), seps2[1].c_str(), seps2[2].c_str(), seps2[3].c_str(),
            seps[0].c_str(), seps[1].c_str(), seps[2].c_str(), seps[3].c_str()

    );
    return res;
};

std::string GetValue1(const char *temp, Info info)
{

    char res[512];

    std::vector<std::string> seps2 = info.tokens2;
    std::vector<std::string> seps = info.tokens1;

    sprintf(res, temp,
            seps2[0].c_str(), seps2[1].c_str(), seps2[2].c_str(), seps2[3].c_str(),
            seps[0].c_str(), seps[1].c_str(), seps[2].c_str(), seps[3].c_str()

    );
    return res;
};

struct Config
{
    std::string path;

};

int main(int argc, char *argv[])
{
    // const std::string path = "faker/render/camera/firstPerson";
    Config config;

    for (int i = 0; i < argc - 1; i++)
    {
        std::string v = argv[i];

        if (v == "-s")
        {
            config.path = argv[i + 1];
        }
    };
    const std::string path = config.path;

    Info info(config.path);
    info.CreateIndex();

    struct CreateInfo
    {
        Info info;
        std::string content;

        void Create()
        {
            std::string path = info.path;

            fs::path _p(path);
            fs::create_directories(_p.parent_path());
            info.Create("CMakeLists.txt");
            
            std::ofstream ofs(path);
            ofs << content;
            ofs.flush();
            ofs.close();
        }
    };

    std::vector<CreateInfo> infos;

    infos.push_back({path + "/Inst.h", GetValue1(instHTemp, info)});
    infos.push_back({path + "/Inst.cpp", GetValue2(instCppTemp, info)});
    infos.push_back({path + "/Serializer.h", GetValue2(serializerHTemp, info)});
    infos.push_back({path + "/Serializer.cpp", GetValue2(serializerCppTemp, info)});
    infos.push_back({path + "/Editor.h", GetValue2(editorHTemp, info)});
    infos.push_back({path + "/Editor.cpp", GetValue2(editorCppTemp, info)});
    infos.push_back({path + "/CMakeLists.txt", GetValue2(cmakeListsTemp, info)});

    for (auto &info : infos)
    {
        info.Create();
    }

     // std::cout << GetValue(instHTemp, seps);
}